#include "stdafx.h"

#include "Engine.h"

 // Private functions
//////////////////////////////////////////////////////////////////////

// returns the start index and end index of move
// returns true, when index successfully found
// index of move may not be found in case of circular jump
// these cases occur rarely, so the are ignored
template<typename BB> 
inline bool GetMoveIndexes(BB* bbPosition, BB* bbMove, bool bWhite, 
												 int& startIndex, int& endIndex)
{
	int sIndex = 0,  eIndex = 0;

	// get STM occupied bit pattern
	BB::value_type occupiedBoard; 											
	BB::value_type occupiedMove; 
	
	if(bWhite)
	{
		occupiedBoard = bbPosition->wm | bbPosition->wk;
		occupiedMove = bbMove->wm | bbMove->wk;
	}
	else
	{
		occupiedBoard = bbPosition->bm | bbPosition->bk;
		occupiedMove = bbMove->bm | bbMove->bk;
	}

	// calculate start index
	BB::value_type startPattern = occupiedBoard & occupiedMove;
	sIndex = LSBxx<BB>(startPattern);
	if(sIndex < 0)
		return false;

	// calculate end index
	BB::value_type endPattern = occupiedBoard ^ occupiedMove;
	endPattern &= occupiedMove;
	eIndex = LSBxx<BB>(endPattern);
	if(eIndex < 0)
	{
		assert(false);
		return false;
	}

	startIndex = sIndex;
	endIndex = eIndex;
	return true;
}


 // Public API
//////////////////////////////////////////////////////////////////////


void ClearHistoryTable(SEngineData* ed)
{
	memset(ed->HistoryTable, 0, 2*iTableSize*iTableSize*sizeof(int)); 
}

template<typename BB> 
void IncrementMove(SEngineData* ed, BB* bbBoard, BB* bbMove, bool bWhite, int bonus)
{
}

template<> 
void IncrementMove<BitBoard>(SEngineData* ed, BitBoard* bbBoard, BitBoard* bbMove, bool bWhite, int bonus)
{
	if(ed->bUseHistoryTables == false)
		return;

	int index1;
	int index2;
	if(GetMoveIndexes<BitBoard>(bbBoard, bbMove, bWhite, index1, index2) == false)
		return;

	int color = bWhite ? WHITE : BLACK;

	ed->HistoryTable[index1][index2][color]+=bonus;
}

template<> 
void IncrementMove<BitBoard64>(SEngineData* ed, BitBoard64* bbBoard, BitBoard64* bbMove, bool bWhite, int bonus)
{
	if(ed->bUseHistoryTables == false)
		return;

	int index1;
	int index2;
	if(GetMoveIndexes<BitBoard64>(bbBoard, bbMove, bWhite, index1, index2) == false)
		return;

	int color = bWhite ? WHITE : BLACK;

	// we do not know from which side the goes
	ed->HistoryTable[index1][index2][color]+=bonus;
}


template<typename BB> 
void HistoryUpdateScore(SEngineData* ed, BB* bbBoard, BB* bbMoveList, int count, bool bWhite)
{
}

template<>
void HistoryUpdateScore<BitBoard>(SEngineData* ed, BitBoard* bbBoard, BitBoard* bbMoveList, int count, bool bWhite)
{
	if(ed->bUseHistoryTables == false)
		return;

	int color = bWhite ? WHITE : BLACK;

	for(int i = 0; i < count; i++)
	{
		BitBoard* bb = bbMoveList + i;

		int index1;
		int index2;
		if(GetMoveIndexes<BitBoard>(bbBoard, bb, bWhite, index1, index2) == false)
			continue;

		bb->score += ed->HistoryTable[index1][index2][color];
	}
}

template<>
void HistoryUpdateScore<BitBoard64>(SEngineData* ed, BitBoard64* bbBoard, BitBoard64* bbMoveList, int count, bool bWhite)
{
	if(ed->bUseHistoryTables == false)
		return;

	int color = bWhite ? WHITE : BLACK;

	for(int i = 0; i < count; i++)
	{
		BitBoard64* bb = bbMoveList + i;

		int index1;
		int index2;
		if(GetMoveIndexes<BitBoard64>(bbBoard, bb, bWhite, index1, index2) == false)
			continue;

		bb->score += ed->HistoryTable[index1][index2][color];
	}
}


void HistoryTableDoAge(SEngineData* ed)
{
	for(int c = 0; c < 2; c++)
		for(int i = 0; i < iTableSize; i++)
			for(int j = 0; j < iTableSize; j++)
			ed->HistoryTable[i][j][c] >>= 3;
}
